package com.lxhdj.common.aop;

import com.alibaba.fastjson2.JSON;
import com.lxhdj.common.annotation.ApiLog;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.HashMap;
import java.util.Map;

/**
 * 请求日志切面
 */
@Component
@Aspect
@Slf4j
public class RequestLogAspect {
    private final String ExpGetResultDataPonit = "execution(* com.lxhdj.management.controller.*(..))";
    /**
     * 声明一个切入点，范围为controller包下所有的类
     * 注：作为切入点签名的方法必须返回void类型
     */
    @Pointcut("execution(public * com.lxhdj.*.controller.*.*(..))")
    private void signAop() {}

    /**
     * 日志记录
     * @param joinPoint
     * @return
     */
    @Around("@annotation(com.lxhdj.common.annotation.ApiLog)")
//    @Around("signAop()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取请求的参数
        Map<String, Object> map = new HashMap<>();
        // 参数值
        Object[] values = joinPoint.getArgs();
        // 参数名
        String[] names = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < names.length; i++) {
            map.put(names[i], values[i]);
        }
        // 获取log注解
        ApiLog logAnnotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(ApiLog.class);
        String apiName = logAnnotation.value();
        //获取request对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String uri = "[" + request.getMethod() + "]" + request.getRequestURI();
        // 请求目标方法名
        String exce = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();

        log.info("{}, {}, 请求目标方法名:{}, 入参：{}", apiName, uri, exce, map);
        long startTime = System.currentTimeMillis();
        Object obj = joinPoint.proceed();//调用执行目标方法
        long endTime = System.currentTimeMillis();
        log.info("{},请求目标的方法:{}, 返回值：{}, 耗时：{}ms", apiName, exce, JSON.toJSONString(obj), endTime - startTime);

        return obj;
    }


}
